package com.ruicar.afs.cloud.gateway.handler.loginprocess;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.security.feign.Oauth2OperationService;
import com.ruicar.afs.cloud.common.core.util.Base64Util;
import com.ruicar.afs.cloud.common.core.util.ClientTypeUtil;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.core.util.RsaUtils;
import com.ruicar.afs.cloud.gateway.util.AfsGateWayHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public interface LoginProcess {
    List<ClientTypeUtil.ClientTypeEnum> supportClientType();
    default Mono<ServerResponse> handle(ServerRequest request){
        Map<String,String> headers = getHeader(request);
        return request.bodyToMono(String.class)
                .flatMap(str ->{
                    Map<String,String> map = JSON.parseObject(str,Map.class);
                    map.put(CommonConstants.GRANT_TYPE, "password");
                    checkBody(map);
                    checkPassWord(map);
                    return Mono.just(map);
                })
                .flatMap(map-> doLogin(map,getHeader(request)))
                .doOnError(e -> ServerResponse.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(IResponse.fail(e.getMessage()))));
    };


    default  Map<String, String> getHeader(ServerRequest request) {
        ClientTypeUtil.ClientTypeEnum clientType = AfsGateWayHelper.getClientType(request);
        Map<String, String> requestHeader = new HashMap<>(8);
        requestHeader.put(CommonConstants.AUTHORIZATION, "Basic " + Base64Util.encode((clientType.getClientId() + ":" + clientType.getClientSecret()).getBytes()));
        requestHeader.putAll(request.headers().asHttpHeaders().toSingleValueMap());
        requestHeader.putAll(request.headers().asHttpHeaders().toSingleValueMap().entrySet().stream().collect(Collectors.toMap(entry->entry.getKey().toLowerCase(), Map.Entry::getValue)));
        checkHeader(requestHeader);
        return requestHeader;
    }
    void checkHeader(Map<String,String> headers);
    void checkBody(Map<String,String> bodyParams);
    default void checkPassWord( Map<String, String> requestParam)  {
        String password = requestParam.get(CommonConstants.PASSWORD);
        if (StrUtil.isNotBlank(password)) {
            password = RsaUtils.getInstance().decryptByPrivateKeyToString(password);
            if (StrUtil.isBlank(password)) {
                throw new RuntimeException("用户名或密码错误");
            }
            requestParam.put(CommonConstants.PASSWORD, password.trim());
        }else {
            throw new RuntimeException("用户名或密码错误");
        }
    }
    Oauth2OperationService getOauthClient();

    default  Mono<ServerResponse> doLogin(Map<String, String> requestParam,Map<String, String> headers){
        Object object = getOauthClient().login(requestParam, headers);
        if (object instanceof IResponse) {
            if(StringUtils.equalsIgnoreCase(((IResponse)object).getCode(),CommonConstants.FAIL)){
               return ServerResponse.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(object));
            }
            return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(object));
        }
        return ServerResponse.status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(BodyInserters.fromValue(new IResponse(object, "success")));
    }
}
